home *** CD-ROM | disk | FTP | other *** search
- /**
- GRAB Graph Layout and Browser System
-
- Copyright (c) 1986, 1988 Regents of the University of California
- Copyright (c) 1989, Tera Computer Company
- **/
-
- /* digraph.h -- definitions for a DIGRAPH */
-
- #ifndef digraph_h
- #define digraph_h
-
- #include <stdio.h>
- #include "attribute.h"
- #include "set.h"
-
- #define new(p, t) {p = (t *) malloc(sizeof(t));}
- /* Mimic Pascal new function */
-
- #define dispose(p) free((char *) p)
-
- #define MAXNODES 2000 /* maximum number of nodes */
- #define MAXHASH 511 /* vertex hash table size (it isn't prime) */
-
- #define NO_BC -1.0 /* indicates no barycenter */
-
- typedef enum {UP, DOWN, UPDOWN} DIRECTION; /* for bc's and priorities */
- #define NUM_DIRECTION 3
-
- #define MAX(A,B) ( (A) > (B) ? (A) : (B) )
- #define MIN(A,B) ( (A) < (B) ? (A) : (B) )
-
- typedef int VNO; /* vertex number */
- typedef int LNO; /* level number */
-
- typedef struct outedge OUTEDGE;
-
- struct outedge
- {
- VNO to_vno; /* vertex at the head of the edge */
- BOOL edge_reversed; /* has this edge been reversed? */
- BRUSH brush; /* how to draw it */
- COLOR color; /* color to draw it */
- char **attributes; /* user-defined attributes for the edge */
- int ordinality; /* for multigraphs; determines whether this is the
- first, second, etc. edge from a to b. Useful
- for identification and layout heuristics */
- OUTEDGE *next; /* next edge */
- };
-
- typedef struct inedge INEDGE;
-
- struct inedge
- {
- VNO from_vno; /* vertex at the head of the edge */
- BOOL edge_reversed; /* has this edge been reversed? */
- int ordinality; /* for multigraphs; determines whether this is the
- first, second, etc. edge from a to b. Useful
- for identification and layout heuristics */
- INEDGE *next; /* next inedge */
- };
-
- typedef struct vertex VERTEX;
-
- struct vertex
- {
- char *name; /* name of the vertex */
- VNO vno; /* vertex number */
- VERTEX *next; /* next in chain */
- };
-
- typedef float BC; /* barycenter */
-
- typedef struct node MEMBER;
-
- struct node
- {
- VERTEX *vertex; /* vertex info */
- VNO coalescer_vno; /* vno of the container of this node */
- OUTEDGE *out_edges; /* outgoing edges */
- INEDGE *in_edges; /* incoming edges */
- SET *succ_set; /* succedent set of vertices */
- SET *ante_set; /* antecedent set of vertices */
- /**
- there is a distinction between the antecedents/succedents and the
- in_edges/out_edges of a node. It's best thought of in this way:
- in_edges/out_edges represent the abstract (undrawn) graph.
- Antecedents/succedents represent the layed out graph. Hence,
- coalescer nodes and dummy nodes have no in or out edges, because
- they aren't part of the abstract graph, only the displayed (layed
- out) graph.
-
- Also, because the successor and antecedent sets are *sets*, they
- only indicate links between two nodes. Multiple edges are possible,
- but you can't tell if there are multiple edges without looking at
- the inedge/outedge lists.
-
- These distinction is very important when drawing the graph. Generally,
- routines should only access the successor and ancestor sets directly,
- using the routines in util.c to access the in and out edges.
-
- Finally, just to make things more confusing, note that edges can
- be reversed, and ante and succ sets get reversed along with the edges.
- So, for example, to check for the parents of a node, you must consider
- at both the ancestor and successor sets (or the in and out edge lists).
- **/
- int x_position; /* x position of center of node */
- int y_position; /* y position of center of node */
- int half_width; /* half of width */
- int half_height; /* half of height */
- SHAPE shape; /* shape of node */
- BRUSH brush; /* how to draw it */
- COLOR color; /* color to draw it */
- char **attributes; /* user-defined attributes for the node */
- BOOL coalesced; /* if true, the node is contained in another node.
- /**
- Note: if coalesced is true, displayed had better be false
-
- coalesced nodes should have the proper ante/succ sets, indicating
- their (displayed) neighbors. This facilitates expanding a node.
- fix_ante_succ_sets, in relay.c, properly builds the ante_succ sets
- given the outedge lists.
-
- currently, no coalesced nodes are found in ante/succ sets. Instead,
- the topmost coalescer of the node is given. This makes expansion
- somewhat difficult if the coalescer node has coalescer neighbors
- (because you have to find out which element of the coalescer was
- the original neighbor of the coalescer). The alternative is to
- keep only non-coalescer nodes in ante/succ sets, and chase down the
- chain of coalescer_vno's every time. I expect that chasing down
- the chain would be done often, wheras coalesces and expands are done
- less often, so the current implementation is probably more efficient.
- **/
- BOOL coalescer; /* if true, the node contains other nodes */
- SET *expansion; /* members of a coalescer node */
- BOOL displayed; /* if false, the node is there, but it isn't drawn or
- considered when laying out the graph */
- /* the following fields are considered to be member fields */
- int level_no; /* level number of node */
- int position; /* position on level */
- STATUS status; /* node type: NORMAL or DUMMY */
- int last_dummy; /* e.g. ->name.1, last dummy number used */
- BC bc[NUM_DIRECTION - 1]; /* up and down barycenters (no updown) */
- BOOL is_layed; /* TRUE if this member is layed out */
- int priority[NUM_DIRECTION]; /* up, down, and updown priorities */
- MEMBER *prev; /* previous vertex on the level */
- MEMBER *next; /* next vertex on the level */
- };
-
- typedef struct node NODE;
-
- typedef struct level LEVEL;
-
- struct level
- {
- LNO lno; /* level number */
- SET *members; /* members of this level */
- MEMBER *order; /* order of the members */
- int offset; /* offset from previous level */
- int num_cross; /* number of crossings for this level and next */
- LEVEL *prev; /* previous level */
- LEVEL *next; /* next level */
- };
-
- struct digraph
- {
- VERTEX *hashtbl[MAXHASH]; /* hash table of vertex names */
- int lastnode; /* last node in nodes */
- NODE *nodes[MAXNODES]; /* nodes in the graph */
- LEVEL *levels; /* the digraph levels */
- LEVEL *lastlevel; /* the last level */
- char *title; /* name of digraph */
- int num_node_attributes; /* number of user-defined attributes per node */
- int num_edge_attributes; /* number of user-defined attributes per edge */
- int dist_edge_attribute; /* index of the edge attribute to use as a
- label (currently, it's always 0) */
- int dist_node_attribute; /* index of the node attribute to use as a
- label (currently, it's always 0) */
- char **node_att_names; /* names of the user-defined node attributes */
- char **edge_att_names; /* names of the user-defined edge attributes */
- };
-
- typedef struct digraph DIGRAPH;
-
- #define strsave(p, s) \
- {\
- p = (char *) malloc(strlen(s) + 1); \
- strcpy(p, s); \
- }
-
- #define loop /* nothing */
- #define endloop }}
-
- #define Node_member(node) ((MEMBER *) node)
- #define Member_node(member) ((NODE *) member)
-
- #define Node(digraph, vno) digraph->nodes[vno]
- #define Member(digraph, vno) Node_member(Node(digraph, vno))
-
- /* loop through all the *displayed* nodes */
- #define each_node(digraph, node) \
- {\
- VNO _vno;\
- for (_vno = 0; _vno <= digraph->lastnode; _vno++)\
- {\
- node = Node(digraph, _vno); \
- if (node == NULL || !Displayed(node)) \
- continue;
-
- /* loop through every node */
- #define all_nodes(digraph, node) \
- {\
- VNO _vno;\
- for (_vno = 0; _vno <= digraph->lastnode; _vno++)\
- {\
- node = Node(digraph, _vno); \
- if (node == NULL) \
- continue;
-
- /**
- note that there is no equivalent to each_node for in and out edges,
- because that would imply we're looking at in or out edges (the
- abstract graph) and worried about whether a node is displayed or not
- (the layed out graph). A desire for such a construct indicates muddy
- thinking.
- **/
- #define all_out_edges(node, edge) \
- {\
- OUTEDGE *_next_edge;\
- for (edge = node->out_edges; edge != NULL; edge = _next_edge)\
- {\
- _next_edge = edge->next;
-
- #define all_in_edges(node, edge) \
- {\
- INEDGE *_next_edge;\
- for (edge = node->in_edges; edge != NULL; edge = _next_edge)\
- {\
- _next_edge = edge->next;
-
- #define Title(digraph) (digraph)->title
- #define First_level(digraph) (digraph)->levels
- #define Last_level(digraph) (digraph)->lastlevel
- #define DNodeAttr(digraph) (digraph)->dist_node_attribute
- #define DEdgeAttr(digraph) (digraph)->dist_edge_attribute
- #define NNodeAttr(digraph) (digraph)->num_node_attributes
- #define NEdgeAttr(digraph) (digraph)->num_edge_attributes
- #define NAttrName(digraph, num) (digraph)->node_att_names[num]
- #define EAttrName(digraph, num) (digraph)->edge_att_names[num]
-
- #define To_vno(edge) (edge)->to_vno
- #define From_vno(edge) (edge)->from_vno
- #define Label(edge) (edge)->attributes[(digraph)->dist_edge_attribute]
- #define EAttr(edge, num) (edge)->attributes[num]
- #define Edge_reversed(edge) (edge)->edge_reversed
- #define Ord(edge) (edge)->ordinality
-
- #define Coalesced(node) (node)->coalesced
- #define Coalescer(node) (node)->coalescer
- #define Expansion(node) (node)->expansion
- #define Coalescer_vno(node) (node)->coalescer_vno
- #define Displayed(node) (node)->displayed
- #define Vno(node) (node)->vertex->vno
- #define Name(node) (node)->vertex->name
- #define Text(node) (node)->attributes[(digraph)->dist_node_attribute]
- #define NAttr(node, num) (node)->attributes[num]
- #define Succ_set(node) (node)->succ_set
- #define Ante_set(node) (node)->ante_set
-
- #define Lno(level) (level)->lno
- #define Num_cross(level) (level)->num_cross
- #define Members(level) (level)->members
- #define Order(level) (level)->order
- #define Offset(level) (level)->offset
- #define Prev_level(level) (level)->prev
- #define Next_level(level) (level)->next
-
- #define X_position(member) (member)->x_position
- #define Y_position(member) (member)->y_position
- #define Half_width(member) (member)->half_width
- #define Half_height(member) (member)->half_height
- #define Shape(member) (member)->shape
- #define Brush(member) (member)->brush
- #define Color(member) (member)->color
- #define Level_no(member) (member)->level_no
- #define Position(member) (member)->position
- #define Status(member) (member)->status
- #define Last_dummy(member) (member)->last_dummy
- #define Is_dummy(member) (Status(member) == DUMMY)
- #define Is_layed(member) (member)->is_layed
- #define X_left(member) (X_position(member) - Half_width(member))
- #define X_right(member) (X_position(member) + Half_width(member))
- #define Y_bottom(member) (Y_position(member) - Half_height(member))
- #define Y_top(member) (Y_position(member) + Half_height(member))
- #define Bc(member, direction) (member)->bc[(int) direction]
- #define Has_bc(member, direction) (Bc((member), (int) direction) != NO_BC)
- #define Priority(member, direction) (member)->priority[(int) direction]
- #define Prev_member(member) (member)->prev
- #define Next_member(member) (member)->next
-
-
- #define each_level(digraph, level) \
- {\
- LEVEL * _next_level;\
- for (level = digraph->levels; level != NULL; level = _next_level)\
- {\
- _next_level = Next_level(level);
-
- #define each_level_reverse(digraph, level) \
- {\
- LEVEL * _prev_level;\
- for (level = digraph->lastlevel; level != NULL; level = _prev_level)\
- {\
- _prev_level = Prev_level(level);
-
- #define each_member(level, member) \
- {\
- for (member = Order(level); member != NULL; member = member->next)\
- {
-
-
- #define HALF_CHAR 50
- #define GAP 5 * HALF_CHAR /* space between nodes */
- #define NODE_HALF_HEIGHT 5 * HALF_CHAR
- #define Node_half_width(node) HALF_CHAR * (strlen(Text(node)) + 1)
- #define DUMMY_HALF_WIDTH 2 * HALF_CHAR
- #define NULL_STRING "\0"
- #define EDGE_GAP HALF_CHAR
- /* space between multiple edges into/out of a node */
-
- extern DIGRAPH *digraph;
- extern BOOL straightenEdges;
-
- #endif
-